﻿#pragma once

#include <string>
#include <vector>
#include <stdexcept>
#include "../../stringhelper.h"
#include "../../tangible_filesystem.h"

//C# TO C++ CONVERTER NOTE: Forward class declarations:
namespace LibraryEditor { class MImage; }

using namespace ManagedSquish;

namespace LibraryEditor
{
    /// <summary>
    /// V1 Library
    /// Uses DXT1 Images
    /// </summary>
    class MLibraryV1 final
    {
    public:
        static constexpr int LibVersion = 1;
        static bool Load;
        std::string FileName;

        std::vector<MImage*> Images = std::vector<MImage*>();

        std::vector<int> IndexList = std::vector<int>();
        int Count = 0;
    private:
        bool _initialized = false;

        BinaryReader *_reader;
        FileStream *_stream;

    public:
        virtual ~MLibraryV1()
        {
            delete _reader;
            delete _stream;
        }

        MLibraryV1(const std::string &filename);

        void Initialize();

        void Close();

        void Save();

    private:
        void CheckImage(int index);

    public:
        void ToMLibrary();

        Point *GetOffSet(int index);

        Size *GetSize(int index);

        MImage *GetMImage(int index);

        Bitmap *GetPreview(int index);

        void AddImage(Bitmap *image, short x, short y);

        void ReplaceImage(int Index, Bitmap *image, short x, short y);

        void InsertImage(int index, Bitmap *image, short x, short y);

        void RemoveImage(int index);

        static bool CompareBytes(std::vector<unsigned char> &a, std::vector<unsigned char> &b);

        void RemoveBlanks(bool safe = false);

    public:
        class MImage final
        {
        public:
            short Width = 0, Height = 0, X = 0, Y = 0, ShadowX = 0, ShadowY = 0;
            unsigned char Shadow = 0;
            int Length = 0;
            std::vector<unsigned char> FBytes;
            bool TextureValid = false;
            Bitmap *Image, *Preview;

            //layer 2:
            short MaskWidth = 0, MaskHeight = 0, MaskX = 0, MaskY = 0;

            int MaskLength = 0;
            std::vector<unsigned char> MaskFBytes;
            Bitmap *MaskImage;
            bool HasMask = false;

            virtual ~MImage()
            {
                delete Image;
                delete Preview;
                delete MaskImage;
            }

            MImage(BinaryReader *reader);

            MImage(std::vector<unsigned char> &image, short Width, short Height); //only use this when converting from old to new type!

            MImage(Bitmap *image);

            MImage(Bitmap *image, Bitmap *Maskimage);

        private:
            Bitmap *FixImageSize(Bitmap *input);

//C# TO C++ CONVERTER TODO TASK: C# 'unsafe' code is not converted by C# to C++ Converter:
//            private unsafe byte[] ConvertBitmapToArray(Bitmap input)
//            {
//                byte[] output;
//
//                BitmapData data = input.LockBits(new Rectangle(0, 0, input.Width, input.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
//
//                byte[] pixels = new byte[input.Width * input.Height * 4];
//
//                Marshal.Copy(data.Scan0, pixels, 0, pixels.Length);
//                input.UnlockBits(data);
//
//                for (int i = 0; i < pixels.Length; i += 4)
//                {
//                    //Reverse Red/Blue
//                    byte b = pixels[i];
//                    pixels[i] = pixels[i + 2];
//                    pixels[i + 2] = b;
//
//                    if (pixels[i] == 0 && pixels[i + 1] == 0 && pixels[i + 2] == 0)
//                        pixels[i + 3] = 0; //Make Transparent
//                }
//
//                int count = Squish.GetStorageRequirements(input.Width, input.Height, SquishFlags.Dxt1);
//
//                output = new byte[count];
//                fixed (byte * dest = output)
//                fixed (byte * source = pixels)
//                {
//                    Squish.CompressImage((IntPtr)source, input.Width, input.Height, (IntPtr)dest, SquishFlags.Dxt1);
//                }
//                return output;
//            }

        public:
            void Save(BinaryWriter *writer);

//C# TO C++ CONVERTER TODO TASK: C# 'unsafe' code is not converted by C# to C++ Converter:
//            public unsafe void CreateTexture(BinaryReader reader)
//            {
//                int w = Width + (4 - Width % 4) % 4;
//                int h = Height + (4 - Height % 4) % 4;
//
//                if (w == 0 || h == 0)
//                {
//                    return;
//                }
//
//                Image = new Bitmap(w, h);
//
//                BitmapData data = Image.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
//
//                fixed (byte * source = FBytes)
//                    Squish.DecompressImage(data.Scan0, w, h, (IntPtr)source, SquishFlags.Dxt1);
//
//                byte * dest = (byte * )data.Scan0;
//
//                for (int i = 0; i < h * w * 4; i += 4)
//                {
//                    //Reverse Red/Blue
//                    byte b = dest[i];
//                    dest[i] = dest[i + 2];
//                    dest[i + 2] = b;
//                }
//
//                Image.UnlockBits(data);
//
//                if (HasMask)
//                {
//                    w = MaskWidth + (4 - MaskWidth % 4) % 4;
//                    h = MaskHeight + (4 - MaskHeight % 4) % 4;
//
//                    if (w == 0 || h == 0)
//                    {
//                        return;
//                    }
//                    MaskImage = new Bitmap(w, h);
//
//                    data = MaskImage.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
//
//                    fixed (byte * source = MaskFBytes)
//                        Squish.DecompressImage(data.Scan0, w, h, (IntPtr)source, SquishFlags.Dxt1);
//
//                    dest = (byte * )data.Scan0;
//
//                    for (int i = 0; i < h * w * 4; i += 4)
//                    {
//                        //Reverse Red/Blue
//                        byte b = dest[i];
//                        dest[i] = dest[i + 2];
//                        dest[i + 2] = b;
//                    }
//
//                    MaskImage.UnlockBits(data);
//                }
//            }

            void CreatePreview();
        };
    };
}
